package github.sf.fw.tools.cmd;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import github.sf.fw.utils.RefUtils;
import github.sf.fw.utils.StrUtil;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

/**
 * 用于存放命令的Bean
 * Bean的属性只支持原始类型{String,Number,Boolean}
 *
 * @param <T> 用于描述命令的Bean
 */
public class ReflectionBeanCmd<T> extends BaseCmd {
    private final String baseCmd;

    public ReflectionBeanCmd(Class<T> clazz) {
        this(clazz, "");

    }

    public ReflectionBeanCmd(Class<T> clazz, String baseCmd) {
        this.baseCmd = baseCmd;
        initConfig(clazz);
    }

    private void initConfig(Class<T> clazz) {
        Objects.requireNonNull(clazz, "命令Bean类型为空");
        Set<Field> allDeclaredFields = RefUtils.getAllDeclaredFields(clazz);
        Set<Field> propertiesFields = new HashSet<>();
        for (Field field : allDeclaredFields) {
            String name = field.getName();
            Method getMethod;
            Method setMethod;
            boolean isProps;
            try {
                getMethod = RefUtils.getMethod(clazz, "get" + StrUtil.capitalize(name), new Class[]{});
                setMethod = RefUtils.getMethod(clazz, "set" + StrUtil.capitalize(name), new Class[]{field.getType()});
                isProps = getMethod != null && setMethod != null;
            } catch (RuntimeException e) {
                isProps = false;
            }
            if (isProps) {
                propertiesFields.add(field);
            }
        }

        for (Field propertiesField : propertiesFields) {
            String name = propertiesField.getName();
            nameAndOption.put(name, new CmdOption(name, "--" + name, CPC.BLANK));
        }
    }

    /**
     * 创建main函数的args类型的命令
     *
     * @param bean 命令Bean
     */
    public String[] createMainArgs(T bean) {
        Gson gson = new GsonBuilder().create();
        JsonObject jsonObject = gson.toJsonTree(bean).getAsJsonObject();
        List<String> cmdList = new ArrayList<>();
        for (String paramName : jsonObject.keySet()) {
            CmdOption cmdOption = nameAndOption.get(paramName);
            JsonElement jsonElement = jsonObject.get(paramName);
            if (cmdOption != null && jsonElement.isJsonPrimitive()) {
                if (cmdOption.getCpc() != CPC.NONE && !jsonElement.isJsonNull()) {
                    cmdList.add(cmdOption.getExpr());
                    cmdList.add(jsonElement.getAsString());
                } else {
                    if (jsonElement.getAsJsonPrimitive().isBoolean()) {
                        boolean isUse = jsonElement.getAsBoolean();
                        if (!isUse) {
                            continue;
                        }
                    }
                    cmdList.add(cmdOption.getExpr());
                }
            }
        }
        return cmdList.toArray(new String[0]);
    }

    /**
     * 根据Bean创建命令
     *
     * @param bean 描述命令的Bean
     * @return 命令
     */
    public String buildFromBean(T bean) {
        Gson gson = new GsonBuilder().create();
        JsonObject jsonObject = gson.toJsonTree(bean).getAsJsonObject();
        return super.build(jsonObject);
    }

    @Override
    public String getCommand() {
        return baseCmd;
    }
}
